﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Diagnostics;

namespace FindPath
{
    class Place
    {
        public int mapID { get; set; }
        public string name { get; set; }
        public KeyValuePair<int, Place> parent { get; set; }
        public Dictionary<int, Place> child { get; set; }
        
    }

    public class Pet
    {
        public Pet()
        {
            petType = PlayerType.NORMAL;
        }
        public Pet(int petId, string petName)
        {
            this.petId = petId;
            this.petName = petName;
            this.petLevel = 0;
            petType = PlayerType.NORMAL;
        }
        public int petId { get; set; }
        public string petName { get; set; }
        public byte petLevel { get; set; }
        public PlayerType petType { get; set; }
        public int curHP { get; set; }
        public int curSP { get; set; }
        public int maxHP { get; set; }
        public int addMaxHP { get; set; }
        public int maxSP { get; set; }
        public int addMaxSP { get; set; }
        public int intStatus { get; set; }
        public int addIntStatus { get; set; }
        public int atkStatus { get; set; }
        public int addAtkStatus { get; set; }
        public int defStatus { get; set; }
        public int addDefStatus { get; set; }
        public int hpStatus { get; set; }
        public int spStatus { get; set; }
        public int agiStatus { get; set; }
        public int addAgiStatus { get; set; }
        public int totalExp { get; set; }
        public byte faiStatus { get; set; }
        public TsSkill[] skills { get; set; }
        public PlayerItem[] clothes { get; set; } // 6 slots
    }
    public enum PlayerType {NORMAL = 0x00, REBORN = 0x01, REVO = 0x02}
    public enum PlayerSex { MALE = 0x01, FEMALE = 0x02 }
    public enum PlayerElement {WIND = 0x04, EARTH = 0x01, WATER = 0x02, FIRE = 0x03}
    public class Player
    {
        public Player()
        {
            playerType = PlayerType.NORMAL;
            playerSex = PlayerSex.MALE;
            carryPet = null;
        }
        public long playerId { get; set; }
        public string playerName { get; set; }
        public byte playerLevel { get; set; }
        public PlayerType playerType {get; set;}
        public PlayerSex playerSex { get; set; }
        public PlayerElement playerElement { get; set; }
        public short xCoord { get; set; }
        public short yCoord { get; set; }
        public int currentMap { get; set; }
        public Pet[] carryPet { get; set; }
    }

    public class PlayerComparator : IEqualityComparer<Player>
    {

        bool IEqualityComparer<Player>.Equals(Player x, Player y)
        {
            return (x.playerId == y.playerId);
        }



        public int GetHashCode(Player obj)
        {
            return obj.GetHashCode();
        }
    }

    public class TsCharacter : Player {
        public TsCharacter() : base()
        {
            this.carryPet = new Pet[6];
        }
        public int numGod { get; set; }
        public int numGhost { get; set; }
        public int curHP { get; set; }
        public int curSP { get; set; }
        public int maxHP { get; set; }
        public int addMaxHP { get; set; }
        public int maxSP { get; set; }
        public int addMaxSP { get; set; }
        public int intStatus { get; set; }
        public int addIntStatus { get; set; }
        public int atkStatus { get; set; }
        public int addAtkStatus { get; set; }
        public int defStatus { get; set; }
        public int addDefStatus { get; set; }
        public int hpStatus { get; set; }
        public int spStatus { get; set; }
        public int agiStatus { get; set; }
        public int addAgiStatus { get; set; }
        public int totalExp { get; set; }
        public int statusPointLeft { get; set; }
        public int defaultPet { get; set; }
        public PlayerSkill[] skills { get; set; }
        public PlayerItem[] inventory { get; set; } // 25 slots or more?
        public PlayerItem[] clothes { get; set; } // 6 slots
    }

    public class TsSkill
    {
        public int skillId { get; set; }
        public string name { get; set; }
        public string description { get; set; }
    }
    public class PlayerSkill : TsSkill
    {
        public byte skillLevel { get; set; }
    }
    public enum ItemType { HAT = 0x00, ARMOR = 0x01, WRIST = 0x02, WEAPON = 0x03, SHOES = 0x04, BADGE = 0x05, OTHER = 0x10 };
    public class TsItem
    {
        public int itemId {
            get { return itemId; } 
            set {
                if (value >= 19000 && value <20000) {
                    this.itemType = ItemType.ARMOR;
                } else if (value >= 20000 && value < 21000) {
                    this.itemType = ItemType.HAT;
                } else if (value >= 21000 && value < 22000) {
                    this.itemType = ItemType.SHOES;
                } else if (value >=22000 && value < 24000) {
                    this.itemType = ItemType.BADGE;
                }
                else if (value > 10000 && value < 19000)
                {
                    this.itemType = ItemType.WEAPON;
                }
                else
                {
                    this.itemType = ItemType.OTHER;
                }
            }
        }
        public ItemType itemType { get; set; }
        public string name { get; set; }
        public string description { get; set; }
    }
    public class PlayerItem : TsItem
    {
        public byte quantity { get; set; }
        public byte wearLvl { get; set; }
    }

    public class TsNpc
    {
        public int npcId { get; set; }
        public string name { get; set; }
    }
    class StateObject
    {
        byte[] buffer = new byte[1428];
        public Socket workSocket { get; set; }
        public byte[] Buffer
        {
            get { return buffer;}
            set {buffer = value;}
        }
        public const int BUFFER_SIZE = 1428;
        public string unfinishedPacket;
    }
    public class TsMessage
    {
        public TsMessage(long messageLength, byte[] data)
        {
            this.length = messageLength;
            
            int opCodeLength = 1;
            if (data[0] == 0x01 || data[0] == 0x05 || data[0] == 0x0F || data[0] == 0x17 || data[0] == 0x13 || data[0] == 0x08)
            {
                this.opCode = data[0].ToString("X2") + data[1].ToString("X2");
                opCodeLength = 2;
            }
            else
            {
                this.opCode = data[0].ToString("X2");
            }
            this.data = new byte[messageLength - opCodeLength];
            this.length = messageLength - opCodeLength;
            Array.Copy(data, opCodeLength, this.data, 0, data.Length - opCodeLength);
        }
        public TsMessage(long messageLength, byte[] fullData, int start)
        {
            
            
            int opCodeLength = 1;
            if (fullData[start] == 0x01 || fullData[start] == 0x05 || fullData[start] == 0x0F || fullData[start] == 0x17 || fullData[start] == 0x13 || fullData[start] == 0x08)
            {
                this.opCode = fullData[start].ToString("X2") + fullData[start + 1].ToString("X2");
                opCodeLength = 2;
            }
            else
            {
                this.opCode = fullData[start].ToString("X2");
            }
            this.data = new byte[messageLength - opCodeLength];
            try
            {
                Array.Copy(fullData, start + opCodeLength, this.data, 0, messageLength - opCodeLength);
                this.length = messageLength - opCodeLength;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(WSUtils.printBytes(fullData, fullData.Length) + " " + opCodeLength + " " + messageLength);
            }
            
        }
        public long length { get; set; }
        public string opCode { get; set; }
        public byte[] data { get; set; }
        public override string ToString()
        {
            return "CODE " + this.opCode + "->" + WSUtils.printBytes(this.data, this.data.Length) + " Length " + this.length;
        }
    }

}
